package com.fanh.service.impl;

import com.fanh.common.api.CommonResult;
import com.fanh.common.exception.Asserts;
import com.fanh.common.util.CommonUtil;
import com.fanh.common.util.FileUtil;
import com.fanh.common.util.RequestUtil;
import com.fanh.common.util.SmsCodeUtil;
import com.fanh.dto.UserInfoDetails;
import com.fanh.mapper.SysUserMapper;
import com.fanh.model.SysOffice;
import com.fanh.model.SysUser;
import com.fanh.model.SysUserExample;
import com.fanh.security.util.JwtTokenUtil;
import com.fanh.service.UserService;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.web.multipart.MultipartFile;


@Service("userService")
public class UserServiceImpl implements UserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
    @Value("${minio.endpoint}")
    private String ENDPOINT;
    @Value("${minio.bucketName}")
    private String BUCKET_NAME;
    @Value("${minio.accessKey}")
    private String ACCESS_KEY;
    @Value("${minio.secretKey}")
    private String SECRET_KEY;
    @Value("${minioInternet.endpoint}")
    private String minioInternet;


    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private SysUserMapper  sysUserMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public List<SysUser> getUser(SysUser user) {
        SysUserExample example = new SysUserExample();
        if(user.getPhone() !=null && !user.getPhone().trim().equals("")){
            example.createCriteria().andPhoneEqualTo(user.getPhone());
        }
       List<SysUser> users = sysUserMapper.selectByExample(example);
        return users;
    }

    /**
     *  手机号码， 登录名 ， 微信openID
     * @param userKey
     * @return
     */
    public  SysUser login(String userKey) {
        SysUserExample example = new SysUserExample();

         if(userKey != null && !userKey.equals("")){
             example.or().andLoginNameEqualTo(userKey);
             example.or().andPhoneEqualTo(userKey);
             example.or().andOpenidEqualTo(userKey);
         }else {
             return null;
         }
        List<SysUser> users = sysUserMapper.selectByExample(example);
         if(users!= null && users.size()>0){
             return users.get(0);
         }
         return null;

    }


    @Override
    public String login(String userName, String password) {
        String token = null;
        //密码需要客户端加密后传递
        try {
            SysUserExample example = new SysUserExample();
                example.createCriteria().andLoginNameEqualTo(userName);
            List<SysUser> users = sysUserMapper.selectByExample(example);

            if(users == null || users.size()<1){
                Asserts.fail("用户名密码错误！");
            }

            UserDetails userDetails = new UserInfoDetails(users.get(0));

            if(!passwordEncoder.matches(password,userDetails.getPassword())){
                throw new BadCredentialsException("密码不正确");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails);
        } catch (AuthenticationException e) {
            LOGGER.warn("登录异常:{}", e.getMessage());
            e.printStackTrace();
        }
        return token;
    }

    @Override
    public SysUser phoneRegist(String phone, String name, String password) {

        SysUserExample example = new SysUserExample();

            example.createCriteria().andPhoneEqualTo(phone);

        List<SysUser> users = sysUserMapper.selectByExample(example);

        if(users!= null && users.size()>0){
             Asserts.fail("号码已存在");
        }
        SysUser user = new SysUser();
        user.setId(CommonUtil.uuid());
        user.setName(name);
        user.setUserType("3");

        user.setLoginName(phone);
        user.setMobile(phone);
        user.setPhone(phone);
        user.setPassword(passwordEncoder.encode(password));
        user.setCreateDate(new Date());
        user.setUpdateDate(new Date());
        user.setSex("0");
        user.setDelFlag("0");
        user.setLoginFlag("1");

        user.setCompanyId("1");
        user.setOfficeId("1");
        user.setCreateBy("1");
        user.setUpdateBy("1");

         sysUserMapper.insertSelective(user);
        return  user;
    }

    @Override
    public UserInfoDetails loadUserByUsername(String username) {
        SysUser user = login(username);
        if(user!=null){
            return new UserInfoDetails(user);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
     }

    @Override
     public SysUser getCurrentSysUser() {
        SecurityContext ctx = SecurityContextHolder.getContext();
        Authentication auth = ctx.getAuthentication();
        if(auth.getPrincipal() == null ){
            return null;
        }
        UserInfoDetails userInfoDetails = (UserInfoDetails) auth.getPrincipal();
        return sysUserMapper.selectByPrimaryKey(userInfoDetails.getUser().getId());
    }

    @Override
    public Map<String, Object> wxlogin(String accessToken, String openId) {
        Map<String, Object> map =new HashMap();
        SysUser user=login(openId);
        String  token = "";
        if(user!= null){
            jwtTokenUtil.generateToken(new UserInfoDetails(user));
            map.put("user", user);
            map.put("token", token);
            return  map;
        }
        //验证accessToken 是否失效
        boolean valid = isAccessTokenIsInvalid(accessToken, openId);
        if(!valid){
            Asserts.fail("登录超时，请重试！");
        }

        user = getAndSaveUserInfo(accessToken, openId);
        jwtTokenUtil.generateToken(new UserInfoDetails(user));

        map.put("user", user);
        map.put("token", token);
        return  map;
    }

    private boolean isAccessTokenIsInvalid(String accessToken, String openID) {
        try {
            String url = "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + openID;
            JSONObject resultJson = JSONObject.fromObject(RequestUtil.httpsRequest(url, "POST", null));
             int errorCode = resultJson.getInt("errcode");
            if (errorCode == 0) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    private SysUser getAndSaveUserInfo(String accessToken, String openID)   {
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openID;
        JSONObject userJson = JSONObject.fromObject(RequestUtil.httpsRequest(url, "POST", null));

        String nikeName = userJson.getString("nickname");
        String sex = userJson.getString("sex");
        String image = userJson.getString("headimgurl");

        SysUser user = new SysUser();
        user.setId(CommonUtil.uuid());
        user.setPhoto(image);
        user.setUserType("3");
        user.setLoginName(openID);
        user.setCreateDate(new Date());
        user.setUpdateDate(new Date());
        user.setName(nikeName);
        user.setOpenid(openID);
        user.setSex(sex);
        user.setDelFlag("0");
        user.setLoginFlag("1");


        //没啥用的参数
        user.setCompanyId("1");
        user.setOfficeId("1");
        user.setCreateBy("1");
        user.setUpdateBy("1");

        sysUserMapper.insertSelective(user);

        return user;
    }

    @Override
    public int bingWx(String accessToken, String openId) {
        //获取当前登录用户
        SysUser user = getCurrentSysUser();
        if(user == null){
            Asserts.fail("当前未登录，或token已失效");
        }
        user.setOpenid(openId);
        int count = sysUserMapper.updateByPrimaryKey(user);
        return count;
    }

    @Override
    public int modifyPassword(String phone, String sessionId, String verificationCode, String newPassword) {
        com.alibaba.fastjson.JSONObject jsonObject = SmsCodeUtil.verifySms(sessionId, verificationCode);
        String code = jsonObject.getString("code");
        if ("200".equals(code)) {
            SysUser user =new SysUser();
            user.setPhone(phone);
            List<SysUser> users = getUser(user);
            if(users!=null && users.size()>0){
                user=users.get(0);
                user.setPassword(passwordEncoder.encode(newPassword));
              return   sysUserMapper.updateByPrimaryKey(user);
            }
        } else {
            Asserts.fail("验证码错误");
        }
        return 0;
    }

    @Override
    public SysUser modifyUser(SysUser user, MultipartFile file) {
        if(file != null && !file.isEmpty()){
            String url = FileUtil.upload(file,ENDPOINT,BUCKET_NAME,ACCESS_KEY,SECRET_KEY,minioInternet);
            user.setPhoto(url);
        }

        int count =sysUserMapper.updateByPrimaryKey(user);
        if(count<1){
            Asserts.fail("用户修改失败");
        }
        return user;
    }
}
